package baoycode.db;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

import baoycode.utils.StringUtils;



public class JavaBeanGenerator {

	protected String packageTemplate = "package %s;%n%n";
	protected String importTemplate = "import java.io.Serializable;%n"
			+ "import java.util.Date;%n";
	protected String classDefineTemplate = "%n" + "@SuppressWarnings(\"serial\")%n" + "public class %s  implements Serializable {%n%n";
	
	
	
	protected String attrTemplate = "\tprivate %s %s;%n";
	
	protected String setterTemplate = "\tpublic void %s(%s %s) {%n" + "\t\tthis.%s = %s;%n" + "\t}%n%n";

	protected String getterTemplate = "\tpublic %s %s() {%n" + "\t\treturn %s;%n" + "\t}%n%n";

	protected String baseModelPackageName;
	protected String baseModelOutputDir;
	protected JavaKeyword javaKeyword = JavaKeyword.me;

	public JavaBeanGenerator(String baseModelPackageName, String baseModelOutputDir) {
		if (StringUtils.isBlank(baseModelPackageName)) {
			throw new IllegalArgumentException("baseModelPackageName can not be blank.");
		}
		if (baseModelPackageName.contains("/") || baseModelPackageName.contains("\\")) {
			throw new IllegalArgumentException("baseModelPackageName error : " + baseModelPackageName);
		}
		if (StringUtils.isBlank(baseModelOutputDir)) {
			throw new IllegalArgumentException("baseModelOutputDir can not be blank.");
		}

		this.baseModelPackageName = baseModelPackageName;
		this.baseModelOutputDir = baseModelOutputDir;
	}

	public void generate(List<TableMeta> tableMetas) {
		System.out.println("Generate base model ...");
		System.out.println("Base Model Output Dir: " + baseModelOutputDir);
		for (TableMeta tableMeta : tableMetas) {
			genBaseModelContent(tableMeta);
		}
		writeToFile(tableMetas);
	}

	protected void genBaseModelContent(TableMeta tableMeta) {
		StringBuilder ret = new StringBuilder();
		genPackage(ret);
		genImport(ret);
		genClassDefine(tableMeta, ret);
		for (ColumnMeta columnMeta : tableMeta.columnMetas) {
			genAttrName(columnMeta, ret);
		}
		ret.append(String.format("%n"));
		for (ColumnMeta columnMeta : tableMeta.columnMetas) {
			genSetMethodName(columnMeta, ret);
			genGetMethodName(columnMeta, ret);
		}
		ret.append(String.format("}%n"));
		tableMeta.baseModelContent = ret.toString();
	}

	protected void genPackage(StringBuilder ret) {
		ret.append(String.format(packageTemplate, baseModelPackageName));
	}

	protected void genImport(StringBuilder ret) {
		ret.append(String.format(importTemplate));
	}

	protected void genClassDefine(TableMeta tableMeta, StringBuilder ret) {
		System.out.println(tableMeta.modelName);
		ret.append(String.format(classDefineTemplate, tableMeta.modelName));
	}

	protected void genSetMethodName(ColumnMeta columnMeta, StringBuilder ret) {
		String setterMethodName = "set" + StringUtils.firstCharToUpperCase(columnMeta.attrName);
		// 如果 setter 参数名为 java 语言关键字，则添加下划线前缀 "_"
		String argName = javaKeyword.contains(columnMeta.attrName) ? "_" + columnMeta.attrName : columnMeta.attrName;
		String template = setterTemplate;
		String setter = String.format(template, setterMethodName, columnMeta.javaType, argName, columnMeta.attrName,
				argName);
		ret.append(setter);
	}

	protected void genAttrName(ColumnMeta columnMeta, StringBuilder ret) {
//		System.out.println(columnMeta);
		String attr = String.format(attrTemplate, columnMeta.javaType, columnMeta.attrName);
		ret.append(attr);
	}
	
	protected void genGetMethodName(ColumnMeta columnMeta, StringBuilder ret) {
		String getterMethodName = "get" + StringUtils.firstCharToUpperCase(columnMeta.attrName);
		String getter = String.format(getterTemplate, columnMeta.javaType, getterMethodName, columnMeta.attrName);
		ret.append(getter);
	}

	protected void writeToFile(List<TableMeta> tableMetas) {
		try {
			for (TableMeta tableMeta : tableMetas) {
				writeToFile(tableMeta);
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	protected void writeToFile(TableMeta tableMeta) throws IOException {
		File dir = new File(baseModelOutputDir);
		if (!dir.exists()) {
			dir.mkdirs();
		}

		String target = baseModelOutputDir + File.separator + tableMeta.modelName + ".java";
		FileWriter fw = new FileWriter(target);
		try {
			fw.write(tableMeta.baseModelContent);
		} finally {
			fw.close();
		}
	}
}
